package com.idealighter.game.web.checklevel.laba.service;

import com.google.common.collect.Table;
import com.google.inject.Inject;
import com.google.inject.Singleton;

import com.idealighter.game.dictionary.dic.FruitslotBonusNumCfgDic;
import com.idealighter.game.games.fruitslot.common.FruitslotReward;
import com.idealighter.game.games.fruitslot.common.FruitslotRewardType;
import com.idealighter.game.games.fruitslot.common.RewardCalculator;
import com.idealighter.game.games.fruitslot.dto.LineRewardIcons;
import com.idealighter.game.games.fruitslot.struct.FruistlotBasket;
import com.idealighter.game.games.fruitslot.struct.FruitslotSeat;
import com.idealighter.game.web.checklevel.laba.controller.dto.LaBaIconInputDto;
import com.idealighter.game.web.checklevel.laba.service.bo.LaBaCheckResultBo;
import com.idealighter.utils.check.EmptyUtil;
import com.idealighter.utils.code.RandCodeUtil;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import lombok.Data;

@Singleton
public class LaBaBasicControlCheck {
  // 图标行数
  public static final int ICON_ROWS = 3;
  // 图标列数
  public static final int ICON_COLUMNS = 5;
  @Inject
  private FruitslotBonusNumCfgDic fruitslotBonusNumCfgDic;
  private static List<Long> betList = new ArrayList<Long>();

  static {
    betList.add(10L);
    betList.add(20L);
  }

  /**
   * 校验.
   * 
   * @param basicInputs 基础输入.
   * @return 结果.
   */
  public List<LaBaCheckResultBo> check(List<LaBaIconInputDto> basicInputs) {
    List<LaBaIconWeight> weights = null;
    List<LaBaCheckResultBo> result = new ArrayList<LaBaCheckResultBo>();
    for (LaBaIconInputDto item : basicInputs) {
      weights = new ArrayList<LaBaIconWeight>();
      LaBaIconWeight weight = new LaBaIconWeight();
      weight.setId(1);
      weight.setWeight(item.getWild());
      weights.add(weight);

      weight = new LaBaIconWeight();
      weight.setId(2);
      weight.setWeight(item.getBonus());
      weights.add(weight);

      weight = new LaBaIconWeight();
      weight.setId(3);
      weight.setWeight(item.getBanana());
      weights.add(weight);

      weight = new LaBaIconWeight();
      weight.setId(4);
      weight.setWeight(item.getWatermelo());
      weights.add(weight);

      weight = new LaBaIconWeight();
      weight.setId(5);
      weight.setWeight(item.getLemon());
      weights.add(weight);

      weight = new LaBaIconWeight();
      weight.setId(6);
      weight.setWeight(item.getBar());
      weights.add(weight);

      weight = new LaBaIconWeight();
      weight.setId(7);
      weight.setWeight(item.getGrape());
      weights.add(weight);

      weight = new LaBaIconWeight();
      weight.setId(8);
      weight.setWeight(item.getStrawberry());
      weights.add(weight);

      weight = new LaBaIconWeight();
      weight.setId(9);
      weight.setWeight(item.getCherry());
      weights.add(weight);

      weight = new LaBaIconWeight();
      weight.setId(10);
      weight.setWeight(item.getApple());
      weights.add(weight);

      weight = new LaBaIconWeight();
      weight.setId(11);
      weight.setWeight(item.getPawpaw());
      weights.add(weight);

      LaBaIconGroup group = new LaBaIconGroup(weights);
      LaBaCheckResultBo checkResult = checkBasic(1000000, group);
      checkResult.setId(item.getId());

      result.add(checkResult);
    }

    return result;
  }

  /**
   * 校验基础.
   * 
   * @param betCount 下注总计.
   * @param iconGroup 图标组合.
   * @return 结果.
   */
  public LaBaCheckResultBo checkBasic(int betCount, LaBaIconGroup iconGroup) {
    FruitslotSeat seat = new FruitslotSeat((byte) 0, null);
    LaBaCheckResultBo result = new LaBaCheckResultBo();
    for (int count = 0; count < betCount; count++) {
      seat.setLine(RandCodeUtil.random(1, 9));
      seat.setBet(RandCodeUtil.randomList(betList));
      Table<Integer, Integer, Integer> icons = seat.getIcons();

      Map<Integer, Long> itemTypeMap = new HashMap<Integer, Long>();
      boolean run = true;
      long leftBonus = 1L;
      long win = 0L;
      while (run) {
        // 合计权重
        int totalWeight = iconGroup.totalWeight;

        for (int i = 0; i < ICON_ROWS; i++) {
          for (int j = 0; j < ICON_COLUMNS; j++) {
            // 随机数
            int rand = RandCodeUtil.random(totalWeight);
            int sum = 0;
            int icon = 0;

            for (LaBaIconWeight iconWeight : iconGroup.getList()) {
              sum += iconWeight.getWeight();
              if (rand < sum) {
                icon = iconWeight.getId();
                break;
              }
            }
            icons.put(i, j, icon);
          }
        }
        FruitslotReward reward = RewardCalculator.calculate(seat.getIcons(),
            fruitslotBonusNumCfgDic.map(), seat.getLine(), seat.getBet());

        // 通过连线判断类型
        if (EmptyUtil.listIsNotEmpty(reward.getLineRewardIconsList())) {
          for (LineRewardIcons item : reward.getLineRewardIconsList()) {
            int icon = item.getIcon();
            Long typeCount = itemTypeMap.get(icon);
            if (typeCount == null) {
              typeCount = 0L;
            }
            itemTypeMap.put(icon, typeCount + 1);
          }
        }

        // 如果是水果篮奖励
        if (reward.getType() == FruitslotRewardType.LOTTERY_REWARD.getType()) {
          result.addSgl(1); // 增加水果篮次数
          // 随机产生水果篮金币
          FruistlotBasket basketRewardDomain =
              reward.getLotteryRewards().get(RandCodeUtil.random(0, 2));
          result.addWinChips(basketRewardDomain.getMultiple() * seat.getBet() * seat.getLine()
              / basketRewardDomain.getRate());
          // result.addWinChips(RandCodeUtil.randomList(reward.lotteryRewards) * seat.bet);
        }
        win += reward.getWin(); // 统计赢的金币
        result.addWinChips(reward.getWin());
        result.addBonus(reward.getBonus()); // 总免费把数
        leftBonus += reward.getBonus();
        leftBonus--; // 剩余bonus次数减少
        if (leftBonus <= 0) {
          run = false;
        }
      }
      if (win > 0) {
        result.addWinCount(1);
      }
      result.addBetCount(1);
      result.addBetChips(seat.getBet() * seat.getLine());
      result.addTypeMap(itemTypeMap);
    }

    return result;
  }



  public static class LaBaIconGroup {
    private int totalWeight = 0;
    private List<LaBaIconWeight> list = new ArrayList<LaBaIconWeight>();

    /**
     * 构造函数 .
     * 
     * @param list .
     */
    public LaBaIconGroup(List<LaBaIconWeight> list) {
      for (LaBaIconWeight item : list) {
        this.totalWeight += item.getWeight();
        this.list.add(item);
      }
    }

    public int getTotalWeight() {
      return totalWeight;
    }

    public List<LaBaIconWeight> getList() {
      return list;
    }
  }

  @Data
  public static class LaBaIconWeight {
    private int id;
    private int weight;
  }
}
